const path = require('path');
const fs = require('fs');

const Router = require('koa-router');
const axios = require('axios');
const MemoryFs = require('memory-fs'); // 与fs一样，它是直接写入在内存中的。
const webpack = require('webpack');
const VueServerRenderer = require('vue-server-renderer');

const serverRender = require('./server-render');

// 获取到webpack的配置文件
const serverConfig = require('../../build/webpack.config.server');
const serverCompiler = webpack(serverConfig);
const mfs = new MemoryFs();

serverCompiler.outputFileSystem = mfs; // serverCompiler编译后的文件输出在 memory-fs 中

let bundle; // 记录生成的文件

// 让koa去驱动wabpack进行编译打包
serverCompiler.watch({}, (err, stats) => {
  if (err) throw err;

  stats = stats.toJson();

  // 获取到编译时的错误信息
  stats.errors.forEach(error => {
    console.log(error);
  });

  stats.warnings.forEach(warn => {
    console.log(warn);
  })

  // 读取生成的bundle文件
  const bundlePath = path.join(serverConfig.output.path, 'vue-ssr-server-bundle.json')

  bundle = JSON.parse(mfs.readFileSync(bundlePath, 'utf-8'));
  console.log(`new bundle file`);

});

const handleSSR = async (ctx) => {
  if (!bundle) {
    ctx.body = 'wait, bundle is creating ......';
    return false;
  }

  // 我们需要把拼接好的html模板放在devServer访问的地址下面去，这样devServer才能够渲染出页面的内容
  // 问题：无法获取到devServer中的信息，devServer同样也是一个单独的进程。
  // 解决：可以通过HTTP请求去获取到devServer中的一些数据信息
  const clientMainfestResp = await axios.get(
    `http://127.0.0.1:8099/vue-ssr-client-manifest.json`
  );
  const clientManifest = clientMainfestResp.data;
  
  // 获取到渲染的模板
  const template = fs.readFileSync(path.join(__dirname, '../server-template.ejs'), 'utf-8');
  const renderer = VueServerRenderer.createBundleRenderer(bundle, {
    inject: false,
    clientManifest,  // 生成带有js script标签的模板文件
  });

  await serverRender(ctx, renderer, template);
}

const router = new Router();

router.get('*', handleSSR);
module.exports = router;